package com.atguigu.stack;

public class Calculator {

    public static void main(String[] args) {
        String nums = "1+2*3-4+5-6/3+8*9";
        int num1, num2, oper;
        int index = 0;
        char ch;
        int result = 0;
        String keepNum = "";
        ArrayStack2 operStack = new ArrayStack2(10);
        ArrayStack2 numStack = new ArrayStack2(10);
        while (true) {
            ch = nums.charAt(index++);
            if (operStack.isOper(ch)) {
                //判断符号栈中是否为空
                if (operStack.isEmpty()) {
                    //为空则直接入栈
                    operStack.push(ch);
                } else {
                    // 如果栈中有其他符号则须判断优先级，若当前符号优先级更高，则直接入栈，否则先从数值栈中取出两个数，符号栈取出一个符号，进行运算
                    int currentPriority = operStack.priority(ch);
                    //若当前符号优先级不大于栈顶，则先将符号栈中优先级大的先取出来运算完
                    while (!operStack.isEmpty() && currentPriority <= operStack.priority(operStack.getTop())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        result = numStack.cal(num1, num2, oper);
                        numStack.push(result);
                    }
                    operStack.push(ch); // 确保当前操作符最终入栈
                }
            } else {
                keepNum += ch;
                if(index<nums.length() && !operStack.isOper(nums.charAt(index))){
                    continue;
                }
                else {
                    numStack.push(Integer.parseInt(keepNum));
                    keepNum = "";
                }
            }
            if(index >= nums.length()){
                break;
            }
        }

        //扫码完字符串后，计算栈中剩余的数据
        while (true){
            if(operStack.isEmpty())
                break;
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            result = numStack.cal(num1, num2, oper);
            numStack.push(result);
        }
        System.out.printf("表达式%s结果是%d",nums,numStack.pop());
    }
}

class ArrayStack2 {
    private int maxSize;
    private int top = -1;
    private int[] stack;//


    public int getMaxSize() {
        return maxSize;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public int getTop() {
        return stack[top];
    }

    public void setTop(int top) {
        this.top = top;
    }

    public int[] getStack() {
        return stack;
    }

    public void setStack(int[] stack) {
        this.stack = stack;
    }

    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int value) {
        if (isFull()) {
            System.out.println("栈满");
            return;
        }
        top++;
        stack[top] = value;
    }

    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空，没有数据");
        }
        int value = stack[top];
        top--;
        return value;
    }

    public void show() {
        if (isEmpty()) {
            System.out.println("栈空，没有数据");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d]=%d\n", i, stack[i]);
        }
    }

    public int peek() {
        return stack[top];
    }

    // 返回运算符的优先级，优先级是程序员来确定，优先级使用数字表示，数字越大，优先级越高
    public int priority(int oper) {
        if (oper == '+' || oper == '-') {
            return 0;
        } else if (oper == '*' || oper == '/')
            return 1;
        else return -1;
    }

    public boolean isOper(int oper) {
        return oper == '+' || oper == '-' || oper == '*' || oper == '/';
    }

    public int cal(int num1, int num2, int oper) {
        int res = 0;
        switch (oper) {
            case '+':
                res = num2 + num1;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num2 * num1;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}
